//
//  ViewController.m
//  CryptoTest
//
//  Created by J on 2021/11/10.
//

#import "ViewController.h"
#include <CommonCrypto/CommonCrypto.h>
#include <Security/SecImportExport.h>

/// 加密 无填充,要求数据长度是 kCCBlockSizeAES128 的整数倍
void aesEncryptWithoutPadding(void) {
    
    CCCryptorStatus     err;
    NSUInteger          keyDataLength;
    NSMutableData *     result;
    size_t              resultLength;
    
    NSData *inputData = [@"0123456789ABCDEF" dataUsingEncoding:NSUTF8StringEncoding];
    NSData *keyData = [@"ABCDEFEDHSHSHAJS" dataUsingEncoding:NSUTF8StringEncoding];
    CCOperation op = kCCEncrypt;
    NSData *outputData = nil;
    NSData *ivData = nil;
    
    // We check for common input problems to make it easier for someone tracing through
    // the code to find problems (rather than just getting a mysterious kCCParamError back
    // from CCCrypt).
    
    err = kCCSuccess;
    if ((inputData.length % kCCBlockSizeAES128) != 0) {
        err = kCCParamError;
    }
    keyDataLength = keyData.length;
    if ( (keyDataLength != kCCKeySizeAES128) && (keyDataLength != kCCKeySizeAES192) && (keyDataLength != kCCKeySizeAES256) ) {
        err = kCCParamError;
    }
    if ( (ivData != nil) && (ivData.length != kCCBlockSizeAES128) ) {
        err = kCCParamError;
    }
    
    NSError *error = nil;
    if (err == kCCSuccess) {
        result = [[NSMutableData alloc] initWithLength:inputData.length];
        
        err = CCCrypt(
                      op,
                      kCCAlgorithmAES,
                      (ivData == nil) ? kCCOptionECBMode : 1,
                      keyData.bytes, keyData.length,
                      ivData.bytes,                                  // will be NULL if ivData is nil
                      inputData.bytes, inputData.length,
                      result.mutableBytes,  result.length,
                      &resultLength
                      );
        
        // In the absence of padding the data out is always the same size as the data in.
        assert(resultLength == [result length]);
        outputData = result;
        
        NSLog(@"加密结果 base64编码为 %@", [result base64EncodedStringWithOptions:0]);
    } else {
        error = [NSError errorWithDomain:@"aaa" code:err userInfo:nil];
        NSLog(@"加密失败");
    }
}

/// 解密 解密数据的长度要是 kCCBlockSizeAES128 整数倍
void aesDecryptWithoutPadding(void) {
    
    CCCryptorStatus     err;
    NSUInteger          keyDataLength;
    NSMutableData *     result;
    size_t              resultLength;
    
    NSData *inputData = [[NSData alloc] initWithBase64EncodedString:@"SVockPevI27KzLGMy3XIIQ==" options:0];
    NSData *keyData = [@"ABCDEFEDHSHSHAJS" dataUsingEncoding:NSUTF8StringEncoding];
    CCOperation op = kCCDecrypt;
    NSData *outputData = nil;
    NSData *ivData = nil;
    
    // We check for common input problems to make it easier for someone tracing through
    // the code to find problems (rather than just getting a mysterious kCCParamError back
    // from CCCrypt).
    
    err = kCCSuccess;
    if ((inputData.length % kCCBlockSizeAES128) != 0) {
        err = kCCParamError;
    }
    keyDataLength = keyData.length;
    if ( (keyDataLength != kCCKeySizeAES128) && (keyDataLength != kCCKeySizeAES192) && (keyDataLength != kCCKeySizeAES256) ) {
        err = kCCParamError;
    }
    if ( (ivData != nil) && (ivData.length != kCCBlockSizeAES128) ) {
        err = kCCParamError;
    }
    
    NSError *error = nil;
    if (err == kCCSuccess) {
        result = [[NSMutableData alloc] initWithLength:inputData.length];
        
        err = CCCrypt(
                      op,
                      kCCAlgorithmAES,
                      (ivData == nil) ? kCCOptionECBMode : 0,
                      keyData.bytes, keyData.length,
                      ivData.bytes,                                  // will be NULL if ivData is nil
                      inputData.bytes, inputData.length,
                      result.mutableBytes,  result.length,
                      &resultLength
                      );
        
        // In the absence of padding the data out is always the same size as the data in.
        assert(resultLength == [result length]);
        outputData = result;
        
        NSLog(@"解密结果 %@",  [[NSString alloc] initWithData: result encoding:NSUTF8StringEncoding]);
    } else {
        error = [NSError errorWithDomain:@"aaa" code:err userInfo:nil];
        NSLog(@"无填充解密失败");
    }
}

/// 加密 无填充,要求数据长度是 kCCBlockSizeAES128 的整数倍
void aesEncryptWithPKCS7Padding(void) {
    
    CCCryptorStatus     err;
    NSUInteger          keyDataLength;
    NSMutableData *     result;
    size_t              resultLength;
    
    NSData *inputData = [@"Hello啊,树哥!1212" dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
    NSData *keyData = [@"ABCDEFEDHSHSHAJSABCDEFEDHSHSHAJS" dataUsingEncoding:NSUTF8StringEncoding];
    CCOperation op = kCCEncrypt;
    NSData *outputData = nil;
    NSData *ivData = nil;
    
    // We check for common input problems to make it easier for someone tracing through
    // the code to find problems (rather than just getting a mysterious kCCParamError back
    // from CCCrypt).
    
    err = kCCSuccess;
    if ( (op == kCCDecrypt) && ((inputData.length % kCCBlockSizeAES128) != 0) ) {
        err = kCCParamError;
    }
    keyDataLength = keyData.length;
    if ( (keyDataLength != kCCKeySizeAES128) && (keyDataLength != kCCKeySizeAES192) && (keyDataLength != kCCKeySizeAES256) ) {
        err = kCCParamError;
    }
    if ( (ivData != nil) && (ivData.length != kCCBlockSizeAES128) ) {
        err = kCCParamError;
    }
    
    NSError *error = nil;
    if (err == kCCSuccess) {
        
        NSUInteger      padLength;
        
        // Padding can expand the data, so we have to allocate space for that.  The rule for block
        // cyphers, like AES, is that the padding only adds space on encryption (on decryption it
        // can reduce space, obviously, but we don't need to account for that) and it will only add
        // at most one block size worth of space.
        
        if (op == kCCEncrypt) {
            padLength = kCCBlockSizeAES128;
        } else {
            padLength = 0;
        }
        result = [[NSMutableData alloc] initWithLength:inputData.length + padLength];
        
        err = CCCrypt(
                      op,
                      kCCAlgorithmAES,
                      ((ivData == nil) ? kCCOptionECBMode : 0) | kCCOptionPKCS7Padding,
                      keyData.bytes, keyData.length,
                      ivData.bytes,                                  // will be NULL if ivData is nil
                      inputData.bytes, inputData.length,
                      result.mutableBytes, result.length,
                      &resultLength
                      );
        if (err == kCCSuccess) {
            // Set the output length to the value returned by CCCrypt.  This is necessary because
            // we have padding enabled, meaning that we might have allocated more space than we needed
            // (in the encrypt case, this is the space we allocated above for padding; in the decrypt
            // case, the output is actually shorter than the input because the padding is removed).
            result.length = resultLength;
            outputData = result;
            NSLog(@"aesEncryptWithPKCS7Padding 加密结果 base64编码为 %@", [result base64EncodedStringWithOptions:0]);
        }
        else {
            error = [NSError errorWithDomain:@"aaa" code:err userInfo:nil];
            NSLog(@"加密失败");
        }
    } else {
        error = [NSError errorWithDomain:@"aaa" code:err userInfo:nil];
        NSLog(@"加密失败");
    }
}

/// 解密 解密数据的长度要是 kCCBlockSizeAES128 整数倍
void aesDecryptWithPKCS7Padding(void) {
    
    CCCryptorStatus     err;
    NSUInteger          keyDataLength;
    NSMutableData *     result;
    size_t              resultLength;
    
    NSData *inputData = [[NSData alloc] initWithBase64EncodedString:@"5jPvAQU/HSlee4KONtikN6PnlXR8X9HtABT0eA0Pwng=" options:NSUTF8StringEncoding];;
    NSData *keyData = [@"ABCDEFEDHSHSHAJSABCDEFEDHSHSHAJS" dataUsingEncoding:NSUTF8StringEncoding];
    CCOperation op = kCCDecrypt;
    NSData *outputData = nil;
    NSData *ivData = nil;
    
    // We check for common input problems to make it easier for someone tracing through
    // the code to find problems (rather than just getting a mysterious kCCParamError back
    // from CCCrypt).
    
    err = kCCSuccess;
    if ( (op == kCCDecrypt) && ((inputData.length % kCCBlockSizeAES128) != 0) ) {
        err = kCCParamError;
    }
    keyDataLength = keyData.length;
    if ( (keyDataLength != kCCKeySizeAES128) && (keyDataLength != kCCKeySizeAES192) && (keyDataLength != kCCKeySizeAES256) ) {
        err = kCCParamError;
    }
    if ( (ivData != nil) && (ivData.length != kCCBlockSizeAES128) ) {
        err = kCCParamError;
    }
    
    NSError *error = nil;
    if (err == kCCSuccess) {
        
        NSUInteger      padLength;
        
        // Padding can expand the data, so we have to allocate space for that.  The rule for block
        // cyphers, like AES, is that the padding only adds space on encryption (on decryption it
        // can reduce space, obviously, but we don't need to account for that) and it will only add
        // at most one block size worth of space.
        
        if (op == kCCEncrypt) {
            padLength = kCCBlockSizeAES128;
        } else {
            padLength = 0;
        }
        result = [[NSMutableData alloc] initWithLength:inputData.length + padLength];
        
        err = CCCrypt(
                      op,
                      kCCAlgorithmAES,
                      ((ivData == nil) ? kCCOptionECBMode : 0) | kCCOptionPKCS7Padding,
                      keyData.bytes, keyData.length,
                      ivData.bytes,                                  // will be NULL if ivData is nil
                      inputData.bytes, inputData.length,
                      result.mutableBytes, result.length,
                      &resultLength
                      );
        if (err == kCCSuccess) {
            // Set the output length to the value returned by CCCrypt.  This is necessary because
            // we have padding enabled, meaning that we might have allocated more space than we needed
            // (in the encrypt case, this is the space we allocated above for padding; in the decrypt
            // case, the output is actually shorter than the input because the padding is removed).
            result.length = resultLength;
            outputData = result;
            NSLog(@"解密结果 %@",  [[NSString alloc] initWithData: result encoding:NSUTF8StringEncoding]);
        }
        else {
            error = [NSError errorWithDomain:@"aaa" code:err userInfo:nil];
            NSLog(@"解密失败");
        }
    } else {
        error = [NSError errorWithDomain:@"aaa" code:err userInfo:nil];
        NSLog(@"解密失败");
    }
}



@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor colorWithRed:arc4random_uniform(255) / 255.0 green:arc4random_uniform(255) / 255.0 blue:arc4random_uniform(255) / 255.0 alpha:1];
    
    //    aesDecryptWithoutPadding();
    //    aesEncryptWithoutPadding();
    //    aesDecryptWithPKCS7Padding();
    //    aesEncryptWithPKCS7Padding();
}

#pragma mark - rsa
///
///  这个方法貌似只支持公钥加密,私钥解密,反之报错,暂时没搞明白为什么
///  暂时用 https://github.com/ideawu/Objective-C-RSA 代替
/// 以下为 rsa的一些测试代码
/// 里面的公钥/私钥均为 PKCS8格式的.不支持pkcs1的
/// /* PKCS1的秘钥,下面是对应的转换后的pkcs8的
/// -----BEGIN PUBLIC KEY-----
/// MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCSCXtgZ6w0ArhkDIDR2G2L8I9w
/// 34dZTalMQnHP/MEBSdbYRESq5uTE1DzeK5vdFqJffKqplMuUyo5x2+UEx6hpuSbL
/// jO5oGD9HhaoXgSv1omnn4UZB7160y5G39SSYdrqzltRs/D1gZ2P8zFw92Y80iIpu
/// atMLEmh2rE4GWNS9FQIDAQAB
/// -----END PUBLIC KEY-----
/// -----BEGIN RSA PRIVATE KEY-----
/// MIICWwIBAAKBgQCSCXtgZ6w0ArhkDIDR2G2L8I9w34dZTalMQnHP/MEBSdbYRESq
/// 5uTE1DzeK5vdFqJffKqplMuUyo5x2+UEx6hpuSbLjO5oGD9HhaoXgSv1omnn4UZB
/// 7160y5G39SSYdrqzltRs/D1gZ2P8zFw92Y80iIpuatMLEmh2rE4GWNS9FQIDAQAB
/// AoGABLGXuZC1EQB7x+g7xU+p4n/03EsS7csSA4iox83D4xq22qfQqf2J1MznHlNT
/// sYnZf8aUZabwQPQE6Ai9SUE+WtS3P4/x0ux6xdn0GY6RKzWuIaOWDmS+QdIm6K/v
/// VZcNSNIDJtQucyILpgFZM6z9ngZKwFEJYv9KJo3Ek2Osb3ECQQC8VSIHFhMNoLla
/// pXMCaJtnv5Zsf6ExyrFHw0RSmxV3CRYFPMkGBiT7a8H1fNbkjPYRGOXgfVJEvddE
/// OBavMMuvAkEAxoH/w7UtF7u7Y0Up9MH4RDmd9byRO5ppKkS5Y+uGsfONICGZ7mEf
/// jfPyFtj1OeIVi3ms1P42iJe7IFch5iMgewJARgXlO/tCJEwA/qoLY/be6Sk71aVy
/// mp/BYGxCx+/vgC25qULbf0jjkTOUjyDWiW27w8mdFuWho/ttwWiVTpf28wJAdHTv
/// x7ESs0m/tY1t/9mL/PqQYQovafg8mj+XQ7d5Xgy0TpVn6SGxkWX8MMs3kq3AVgMc
/// EhjRhXD+pwp3KLyS4QJAI3PwI2XaEQXCrIo8cT0LiVEsFO4C/VfDD09njBVEyDIK
/// io+csnJUuWbbGHijx6NFub5cDrUymx1l3FvlRmTHXA==
/// -----END RSA PRIVATE KEY-----
///
///  */
/// NSString *publicKey = @"\
/// -----BEGIN PUBLIC KEY-----\
/// MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0/VlX83cXA0Wimy80QK1\
/// R119cLwOrWiO5TD3UvAyKm0wMNZbk74YWmoApENQux9n/wKwWSLW235fV/VSPPCA\
/// E8OL8+AtHlG146z6hODp/ohdUW4RMf8cH6T9l/Ww6Zx8pj8bPYdpmmDPZ6vohDAa\
/// vhKhhRRwumaN0z+m9dLvHlGZ3i5oFZyKJXSxzBqY0qjDqlEyopsPFhSOQ8Tw7OgO\
/// KPzd9C3OG9MZ10Q8ls1amXokXOFtRyzZDzQ06hT+JjYJW1KtNDl5Eu+XK0eZtFHG\
/// txp0RxdCJCQCpbQzCoBFv7kbqau4MRGMhCB7DsFRF22GxXaQlJrAjZW/Di8eT2kD\
/// 3QIDAQAB\
/// -----END PUBLIC KEY-----";
/// //私钥
/// NSString *privateKey =
/// @"-----BEGIN PRIVATE KEY-----\
/// MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJIJe2BnrDQCuGQM\
/// gNHYbYvwj3Dfh1lNqUxCcc/8wQFJ1thERKrm5MTUPN4rm90Wol98qqmUy5TKjnHb\
/// 5QTHqGm5JsuM7mgYP0eFqheBK/WiaefhRkHvXrTLkbf1JJh2urOW1Gz8PWBnY/zM\
/// XD3ZjzSIim5q0wsSaHasTgZY1L0VAgMBAAECgYAEsZe5kLURAHvH6DvFT6nif/Tc\
/// SxLtyxIDiKjHzcPjGrbap9Cp/YnUzOceU1Oxidl/xpRlpvBA9AToCL1JQT5a1Lc/\
/// j/HS7HrF2fQZjpErNa4ho5YOZL5B0ibor+9Vlw1I0gMm1C5zIgumAVkzrP2eBkrA\
/// UQli/0omjcSTY6xvcQJBALxVIgcWEw2guVqlcwJom2e/lmx/oTHKsUfDRFKbFXcJ\
/// FgU8yQYGJPtrwfV81uSM9hEY5eB9UkS910Q4Fq8wy68CQQDGgf/DtS0Xu7tjRSn0\
/// wfhEOZ31vJE7mmkqRLlj64ax840gIZnuYR+N8/IW2PU54hWLeazU/jaIl7sgVyHm\
/// IyB7AkBGBeU7+0IkTAD+qgtj9t7pKTvVpXKan8FgbELH7++ALbmpQtt/SOORM5SP\
/// INaJbbvDyZ0W5aGj+23BaJVOl/bzAkB0dO/HsRKzSb+1jW3/2Yv8+pBhCi9p+Dya\
/// P5dDt3leDLROlWfpIbGRZfwwyzeSrcBWAxwSGNGFcP6nCncovJLhAkAjc/AjZdoR\
/// BcKsijxxPQuJUSwU7gL9V8MPT2eMFUTIMgqKj5yyclS5ZtsYeKPHo0W5vlwOtTKb\
/// HWXcW+VGZMdc\
/// -----END PRIVATE KEY-----";
/// //测试要加密的数据
/// NSString *sourceStr = @"iOS端RSA加密";
/// //公钥加密
/// NSString *encryptStr = [RSA encryptString:sourceStr publicKey:publicKey];
/// NSLog(@"公钥加密私钥解密 加密 %@",encryptStr);
/// //私钥解密
/// NSString *decrypeStr = [RSA decryptString:encryptStr privateKey:privateKey];
///
/// NSLog(@"公钥加密私钥解密 解密 %@",decrypeStr);
///
/// //私钥加密
/// NSString *encryptStr1 = [RSA encryptString:sourceStr privateKey:privateKey];
/// NSLog(@"加密 %@",encryptStr1);
/// //公钥解密
/// NSString *decrypeStr1 = [RSA decryptString:encryptStr1 publicKey:publicKey];
/// NSLog(@"解密 %@",decrypeStr1);

- (void)rsaEncryptWithPublicKey {
    OSStatus                err;
    NSUInteger              smallInputDataLength;
    NSUInteger              keyBlockSize;
    
    NSData *smallInputData = [@"hello,树哥" dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
    
    NSData *data = [[NSData alloc] initWithBase64EncodedString:@"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCAFVbec6rvdi6LWqm0sbpcTowOZXm0RZIA/LEJJtzWldmIb2xuDOZzPHO1hYCaDSQu6On55rQbtEQYqXUJW5td2z2xFcfp0nhNoLhJgPCeoUA5TY3ICwHzdF1ugzSvYGTcWVWz+P8gKtHLTFqTGKFrVAcd7udP3+ilZ9vj8Ctn4QIDAQAB" options:0];
    // 设置属性字典
    NSMutableDictionary *options = [NSMutableDictionary dictionary];
    options[(__bridge id)kSecAttrKeyType] = (__bridge id) kSecAttrKeyTypeRSA;
    options[(__bridge id)kSecAttrKeyClass] = (__bridge id) kSecAttrKeyClassPublic;
    options[(__bridge id)kSecAttrKeySizeInBits] = @2048;
    NSError *error = nil;
    CFErrorRef ee = (__bridge CFErrorRef)error;
    
    // 调用接口获取密钥对象
    SecKeyRef key = SecKeyCreateWithData((__bridge CFDataRef)data, (__bridge CFDictionaryRef)options, &ee);
    
    
    smallInputDataLength = smallInputData.length;
    keyBlockSize = SecKeyGetBlockSize(key);
    
    // Check that the input data length makes sense.  In most cases these checks are
    // redundant (because the underlying crypto operation does the same checks) but
    // it's good to have them here to help with debugging.  If you get the length
    // wrong, you can set a breakpoint here and learn what's wrong.
    
    err = errSecSuccess;
    //
    //            switch (self.padding) {
    //                default:
    //                    assert(NO);
    //                    // fall through
    //                case QCCRSASmallCryptorPaddingPKCS1: {
    //                    assert(keyBlockSize > 11);
    //                    if ((smallInputDataLength + 11) > keyBlockSize) {
    //                        err = errSecParam;
    //                    }
    //                } break;
    //                case QCCRSASmallCryptorPaddingOAEP: {
    //                    // 42 is 2 + 2 * HashLen, where HashLen is the length of the hash
    //                    // use by the OAEP algorithm.  We currently only support OAEP with SHA1,
    //                    // which has a hash length of 20.
    //                    assert(keyBlockSize > 42);
    //                    if ((smallInputDataLength + 42) > keyBlockSize) {
    //                        err = errSecParam;
    //                    }
    //                } break;
    //            }
    //        }
    //    }
    
    // If everything is OK, call the real code.
    
    if (err != errSecSuccess) {
        NSLog(@"RSA失败");
        return;
    }
    
    CFErrorRef          errorCF = NULL;     // Security framework seems to be grumpy if errorCF left uninitialised
    SecKeyAlgorithm     algorithm;
    NSData *            resultData;
    
    // Map our padding constant appropriately.
    algorithm = kSecKeyAlgorithmRSAEncryptionPKCS1;
    resultData = CFBridgingRelease(
                                   SecKeyCreateEncryptedData(
                                                             key,
                                                             algorithm,
                                                             (__bridge CFDataRef) smallInputData,
                                                             &errorCF
                                                             ) );
    //
    //} break;
    //case QCCRSASmallCryptorOperationDecrypt: {
    //    resultData = CFBridgingRelease( SecKeyCreateDecryptedData(
    //                                                              self.key,
    //                                                              algorithm,
    //                                                              (__bridge CFDataRef) self.smallInputData,
    //                                                              &errorCF
    //                                                              ) );
    //} break;
    //}
    
    // Set up the result.
    
    if (resultData == nil) {
        NSLog(@"rsa加密失败");
        //        error = CFBridgingRelease( errorCF );
    } else {
        NSLog(@"rsa加密结果 %@", [resultData base64EncodedStringWithOptions:0]);
        //        smallOutputData = resultData;
        
    }
}


- (void)rsaDecryptWithPrivateKey {
    OSStatus                err;
    NSUInteger              smallInputDataLength;
    NSUInteger              keyBlockSize;
    
    NSData *smallInputData = [[NSData alloc] initWithBase64EncodedString:@"GhQsO/oazxxDpkum/pr8tdwAwVPL3LCemGnWQECLat1ZKciEPZGXBTsbYUL7WE/Ncc3Vc/3KtYNT333DkZYWkwYsNkz21+VHfW+cJwRlrv6lIwZplZfNL+tB0YUYuX4SjQXpLZR0JrI66mGZsJJXF2KhxAgo3ml+rBG//EmwK64=" options:0];
    
    NSData *data = [[NSData alloc] initWithBase64EncodedString:@"MIICXAIBAAKBgQCAFVbec6rvdi6LWqm0sbpcTowOZXm0RZIA/LEJJtzWldmIb2xuDOZzPHO1hYCaDSQu6On55rQbtEQYqXUJW5td2z2xFcfp0nhNoLhJgPCeoUA5TY3ICwHzdF1ugzSvYGTcWVWz+P8gKtHLTFqTGKFrVAcd7udP3+ilZ9vj8Ctn4QIDAQABAoGAMXCLPIinVZFnu/C+CvqDdff3xeLTjItCJVFkwKSYn9ftxOVFlGE0XwzZmRq0HkKuUdEj54tuwDbgBij6/Sa4HHkxIdfUMHdK3NQCZnRTOPu0xNiqPvSq/4BqQIdHT8/vo4LycBu8YOOhUz/tkuCWbj+n3PDSdQ7Bl9It8rmGjkUCQQCAGdhhOUy1pXdIhvA7AVs9aixYBPdkGbI4XeMoBmyEfm0noT2mLOwce9jjlEAP9y2hkRN6ZA47YbKJcRFkhxAnAkEA//b+y+nHoYqHvthxGREZxJ/K++Dr8iX0ER+LLcPHqx5FUAY4JVaAw4nNRvn3sOxlSOkjHC7rXpKZ0Sw+IlfEtwJALisidUf1gbI1H4qiomGGxMezW7XOg+FO/km4SQCns8jtBk9yrKWcI1fvf3Y68IYhiA2Fe6L8DiLT+f0qS5TyGQJBAJy03/uBbenVgRPzORKqqIb7eW9JncpLOCh/klr7YLO/vZmnpRoe4ohURmvsv5r+r2e66/bmNs1YnXk1R/kImPMCQEV7lQ/jM9keE1resDV58m8DiLZIIOqm3DLrSbvDRM7lAinyRWOOMyAg798CzSn6fjZTYD7RbY+gvg1ZQHCzVmo=" options:0];
    // 设置属性字典
    NSMutableDictionary *options = [NSMutableDictionary dictionary];
    options[(__bridge id)kSecAttrKeyType] = (__bridge id) kSecAttrKeyTypeRSA;
    options[(__bridge id)kSecAttrKeyClass] = (__bridge id) kSecAttrKeyClassPrivate;
    options[(__bridge id)kSecAttrKeySizeInBits] = @2048;
    NSError *error = nil;
    CFErrorRef ee = (__bridge CFErrorRef)error;
    
    // 调用接口获取密钥对象
    SecKeyRef key = SecKeyCreateWithData((__bridge CFDataRef)data, (__bridge CFDictionaryRef)options, &ee);
    
    
    smallInputDataLength = smallInputData.length;
    keyBlockSize = SecKeyGetBlockSize(key);
    
    // Check that the input data length makes sense.  In most cases these checks are
    // redundant (because the underlying crypto operation does the same checks) but
    // it's good to have them here to help with debugging.  If you get the length
    // wrong, you can set a breakpoint here and learn what's wrong.
    
    err = errSecSuccess;
    //
    //            switch (self.padding) {
    //                default:
    //                    assert(NO);
    //                    // fall through
    //                case QCCRSASmallCryptorPaddingPKCS1: {
    //                    assert(keyBlockSize > 11);
    //                    if ((smallInputDataLength + 11) > keyBlockSize) {
    //                        err = errSecParam;
    //                    }
    //                } break;
    //                case QCCRSASmallCryptorPaddingOAEP: {
    //                    // 42 is 2 + 2 * HashLen, where HashLen is the length of the hash
    //                    // use by the OAEP algorithm.  We currently only support OAEP with SHA1,
    //                    // which has a hash length of 20.
    //                    assert(keyBlockSize > 42);
    //                    if ((smallInputDataLength + 42) > keyBlockSize) {
    //                        err = errSecParam;
    //                    }
    //                } break;
    //            }
    //        }
    //    }
    
    // If everything is OK, call the real code.
    
    if (err != errSecSuccess) {
        NSLog(@"RSA失败");
        return;
    }
    
    CFErrorRef          errorCF = NULL;     // Security framework seems to be grumpy if errorCF left uninitialised
    SecKeyAlgorithm     algorithm;
    NSData *            resultData;
    
    // Map our padding constant appropriately.
    algorithm = kSecKeyAlgorithmRSAEncryptionPKCS1;
//    resultData = CFBridgingRelease(
//                                   SecKeyCreateEncryptedData(
//                                                             key,
//                                                             algorithm,
//                                                             (__bridge CFDataRef) smallInputData,
//                                                             &errorCF
//                                                             ) );
    //
    //} break;
    //case QCCRSASmallCryptorOperationDecrypt: {
        resultData = CFBridgingRelease( SecKeyCreateDecryptedData(
                                                                  key,
                                                                  algorithm,
                                                                  (__bridge CFDataRef) smallInputData,
                                                                  &errorCF
                                                                  ) );
    //} break;
    //}
    
    // Set up the result.
    
    if (resultData == nil) {
        NSLog(@"rsa解密失败");
        //        error = CFBridgingRelease( errorCF );
    } else {
        NSLog(@"rsa解密结果 %@",  [[NSString alloc] initWithData: resultData encoding:NSUTF8StringEncoding]);
        //        smallOutputData = resultData;
        
    }
}


@end
